package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/golang-jwt/jwt/v5"
)

// Centrifugo 配置
const (
	centrifugoURL    = "http://localhost:8000"
	centrifugoAPIKey = "RqhDW7JtdDO1fUu9Cf03PIq2ni-AvzigG-zNAKjf1qn7dB8KK-6WYhUgDJ8ZQlw6oEbmMt3Q2P9XV9rv6SinNQ" //http_api
	secretKey        = "ZjWdCul7JPkOY4e2xKBUrrlDsZ0T1F0MwV6pTRkNTPGP9g_w30RkWmxej2Pb4R5Pb66wDZvu0td6b6iJrFk2pA" //hmac_secret_key
)

// 生成JWT Token
func generateToken(userID string) (string, error) {
	claims := jwt.MapClaims{
		"sub": userID,
		"exp": time.Now().Add(24 * time.Hour).Unix(),
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString([]byte(secretKey))
}

// 发布消息到Centrifugo
func publishToChannel(channel string, data map[string]interface{}) error {
	payload := map[string]interface{}{
		"channel": channel,
		"data":    data,
	}

	jsonData, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("JSON编码失败: %v", err)
	}

	req, err := http.NewRequest("POST", centrifugoURL+"/api/publish", bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("创建请求失败: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "apikey "+centrifugoAPIKey)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("HTTP请求失败: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("API返回错误: %s", resp.Status)
	}

	fmt.Printf("✅ 消息发布到频道 [%s] 成功\n", channel)
	return nil
}

// HTTP处理函数
func tokenHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
	w.Header().Set("Access-Control-Allow-Headers", "Content-Type")

	if r.Method == "OPTIONS" {
		w.WriteHeader(http.StatusOK)
		return
	}

	userID := r.URL.Query().Get("user")
	if userID == "" {
		userID = "user-" + fmt.Sprintf("%d", time.Now().Unix())
	}

	token, err := generateToken(userID)
	if err != nil {
		http.Error(w, fmt.Sprintf("生成token失败: %v", err), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]string{
		"token":  token,
		"userId": userID,
	})

	fmt.Printf("🔑 为用户 [%s] 生成Token成功\n", userID)
}

func publishHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
	w.Header().Set("Access-Control-Allow-Headers", "Content-Type")

	if r.Method == "OPTIONS" {
		w.WriteHeader(http.StatusOK)
		return
	}

	var request struct {
		Channel string                 `json:"channel"`
		Message map[string]interface{} `json:"message"`
	}

	if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
		http.Error(w, "无效的请求数据", http.StatusBadRequest)
		return
	}

	if err := publishToChannel(request.Channel, request.Message); err != nil {
		http.Error(w, "发布消息失败: "+err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"status":  "success",
		"message": "消息发送成功",
		"channel": request.Channel,
	})
}

// 测试接口：自动发送演示消息
func demoHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")

	channels := []string{"news", "updates", "notifications"}
	messages := []map[string]interface{}{
		{"text": "欢迎使用实时消息系统!", "type": "welcome"},
		{"text": "这是一条测试消息", "time": time.Now().Format("15:04:05")},
		{"text": "系统运行正常", "status": "ok"},
	}

	for i, channel := range channels {
		if err := publishToChannel(channel, messages[i]); err != nil {
			log.Printf("演示消息发送失败: %v", err)
		}
		time.Sleep(500 * time.Millisecond)
	}

	json.NewEncoder(w).Encode(map[string]string{
		"status": "演示消息已发送",
	})
}

func main() {
	http.HandleFunc("/token", tokenHandler)
	http.HandleFunc("/publish", publishHandler)
	http.HandleFunc("/demo", demoHandler)

	fmt.Println("🚀 Go 服务器启动在 :8080")
	fmt.Println("📋 前端可访问以下接口:")
	fmt.Println("   GET  http://localhost:8080/token?user=用户名")
	fmt.Println("   POST http://localhost:8080/publish")
	fmt.Println("   GET  http://localhost:8080/demo (发送演示消息)")

	log.Fatal(http.ListenAndServe(":8080", nil))
}
